/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zlang_in.h"

struct ZlangObject *AllocObject( struct ZlangRuntime *rt )
{
	struct ZlangObject	*obj = NULL ;
	
	if( list_empty( & (rt->objs_cache) ) )
	{
		obj = (struct ZlangObject *)ZLMALLOC( sizeof(struct ZlangObject) ) ;
		if( obj == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for object" )
			return NULL;
		}
	}
	else
	{
		obj = list_first_entry( & (rt->objs_cache) , struct ZlangObject , obj_cache_node ) ;
		list_del( & (obj->obj_cache_node) );
	}
	
	memset( obj , 0x00 , sizeof(struct ZlangObject) );
	
	return obj;
}

int FreeObject( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	list_add_tail( & (obj->obj_cache_node) , & (rt->objs_cache) );
	
	return 0;
}

void FreeObjectsCache( struct ZlangRuntime *rt )
{
	struct ZlangObject		*obj = NULL ;
	struct ZlangObject		*next_obj = NULL ;
	
	list_for_each_entry_safe( obj , next_obj , & (rt->objs_cache) , struct ZlangObject , obj_cache_node )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ZLFREE obj[%p][%s] cache" , obj , GetObjectName(obj) )
		list_del( & (obj->obj_cache_node) );
		ZLFREE( obj );
	}
	
	return;
}

int DestractObject( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	int		nret = 0 ;
	
	if( obj == NULL || obj->props_enti == NULL )
		return 0;
	
	if( HadObjectDestracted(obj) == 0 && GetFunctionsEntityDestractorFunction(obj->funcs_enti) )
	{
		nret = InterpretExpression_InvokeDefaultConstractorOrDestractorFunction( rt , NULL , NULL , IS_DESTRACTOR , obj ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterpretExpression_InvokeDefaultConstractorOrDestractorFunction failed[%d]" , nret )
		}
		
		SetObjectDestracted(obj);
	}
	
	return nret;
}

unsigned char HadObjectConstracted( struct ZlangObject *obj )
{
	if( obj->props_enti == NULL )
		return 0;
	
	return obj->props_enti->had_constracted;
}

unsigned char HadObjectDestracted( struct ZlangObject *obj )
{
	if( obj->props_enti == NULL )
		return 0;
	
	return obj->props_enti->had_destracted;
}

void SetObjectConstracted( struct ZlangObject *obj )
{
	obj->props_enti->had_constracted = 1 ;
	return;
}

void SetObjectDestracted( struct ZlangObject *obj )
{
	obj->props_enti->had_destracted = 1 ;
	return;
}

struct ZlangPropertiesEntity *AllocPropertiesEntity( struct ZlangRuntime *rt )
{
	struct ZlangPropertiesEntity	*props_enti = NULL ;
	
	if( list_empty( & (rt->props_entis_cache) ) )
	{
		props_enti = (struct ZlangPropertiesEntity *)ZLMALLOC( sizeof(struct ZlangPropertiesEntity) ) ;
		if( props_enti == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for entity" )
			return NULL;
		}
	}
	else
	{
		props_enti = list_first_entry( & (rt->props_entis_cache) , struct ZlangPropertiesEntity , props_enti_cache_node ) ;
		list_del( & (props_enti->props_enti_cache_node) );
	}
	
	memset( props_enti , 0x00 , sizeof(struct ZlangPropertiesEntity) );
	
#if defined(__linux__)
	__sync_add_and_fetch( & (props_enti->refer_count) , 1 );
#elif defined(_WIN32)
	InterlockedIncrement( & (props_enti->refer_count) );
#endif
	
	return props_enti;
}

int FreePropertiesEntity( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangPropertiesEntity *props_enti )
{
#if defined(__linux__)
	if( __sync_sub_and_fetch( & (props_enti->refer_count) , 1 ) == 0 )
	{
		DestractObject( rt , obj );
		
		if( obj->funcs_enti && obj->funcs_enti->direct_funcs && obj->funcs_enti->direct_funcs->destroy_direct_prop_func && props_enti->direct_prop )
		{
			obj->funcs_enti->direct_funcs->destroy_direct_prop_func( rt , obj ) ; props_enti->direct_prop = NULL ;
		}
		
		DestroyEntityPropertiesTree( props_enti );
		
		list_add_tail( & (props_enti->props_enti_cache_node) , & (rt->props_entis_cache) );
	}
#elif defined(_WIN32)
	if( InterlockedDecrement( & (props_enti->refer_count) ) == 0 )
	{
		DestractObject( rt , obj );
		
		if( obj->funcs_enti && obj->funcs_enti->direct_funcs && obj->funcs_enti->direct_funcs->destroy_direct_prop_func && props_enti->direct_prop )
		{
			obj->funcs_enti->direct_funcs->destroy_direct_prop_func( rt , obj ) ; props_enti->direct_prop = NULL ;
		}
		
		DestroyEntityPropertiesTree( props_enti );
		
		list_add_tail( & (props_enti->props_enti_cache_node) , & (rt->props_entis_cache) );
	}
#endif
	
	return 0;
}

void FreePropertiesEntityCache( struct ZlangRuntime *rt )
{
	struct ZlangPropertiesEntity		*props_enti = NULL ;
	struct ZlangPropertiesEntity		*next_props_enti = NULL ;
	
	list_for_each_entry_safe( props_enti , next_props_enti , & (rt->props_entis_cache) , struct ZlangPropertiesEntity , props_enti_cache_node )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ZLFREE prop enti[%p] cache" , props_enti )
		list_del( & (props_enti->props_enti_cache_node) );
		ZLFREE( props_enti );
	}
	
	return;
}

struct ZlangFunctionsEntity *AllocFunctionsEntity( struct ZlangRuntime *rt )
{
	struct ZlangFunctionsEntity	*funcs_enti = NULL ;
	
	if( list_empty( & (rt->funcs_entis_cache) ) )
	{
		funcs_enti = (struct ZlangFunctionsEntity *)ZLMALLOC( sizeof(struct ZlangFunctionsEntity) ) ;
		if( funcs_enti == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for funcs entity" )
			return NULL;
		}
	}
	else
	{
		funcs_enti = list_first_entry( & (rt->funcs_entis_cache) , struct ZlangFunctionsEntity , funcs_enti_cache_node ) ;
		list_del( & (funcs_enti->funcs_enti_cache_node) );
	}
	
	memset( funcs_enti , 0x00 , sizeof(struct ZlangFunctionsEntity) );
	
#if defined(__linux__)
	__sync_add_and_fetch( & (funcs_enti->refer_count) , 1 );
#elif defined(_WIN32)
	InterlockedIncrement( & (funcs_enti->refer_count) );
#endif
	
	return funcs_enti;
}

int FreeFunctionsEntity( struct ZlangRuntime *rt , struct ZlangFunctionsEntity *funcs_enti )
{
#if defined(__linux__)
	if( __sync_sub_and_fetch( & (funcs_enti->refer_count) , 1 ) == 0 )
	{
		DestroyFunctionsEntityFunctionsTreeByFunctionName( funcs_enti );
		DestroyFunctionsEntityFunctionsTreeByFullFunctionName( funcs_enti );
		
		list_add_tail( & (funcs_enti->funcs_enti_cache_node) , & (rt->funcs_entis_cache) );
	}
#elif defined(_WIN32)
	if( InterlockedDecrement( & (funcs_enti->refer_count) ) == 0 )
	{
		DestroyFunctionsEntityFunctionsTreeByFunctionName( funcs_enti );
		DestroyFunctionsEntityFunctionsTreeByFullFunctionName( funcs_enti );
		
		list_add_tail( & (funcs_enti->funcs_enti_cache_node) , & (rt->funcs_entis_cache) );
	}
#endif
	
	return 0;
}

void FreeFunctionsEntityCache( struct ZlangRuntime *rt )
{
	struct ZlangFunctionsEntity		*funcs_enti = NULL ;
	struct ZlangFunctionsEntity		*next_funcs_enti = NULL ;
	
	list_for_each_entry_safe( funcs_enti , next_funcs_enti , & (rt->funcs_entis_cache) , struct ZlangFunctionsEntity , funcs_enti_cache_node )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "ZLFREE funcs enti[%p]->direct_funcs[%p][%s] cache" , funcs_enti , funcs_enti->direct_funcs , (funcs_enti->direct_funcs?funcs_enti->direct_funcs->type_name:NULL) )
		list_del( & (funcs_enti->funcs_enti_cache_node) );
		DestroyFunctionsEntityFunctionsTreeByFunctionName( funcs_enti );
		DestroyFunctionsEntityFunctionsTreeByFullFunctionName( funcs_enti );
		ZLFREE( funcs_enti );
	}
	
	return;
}

static inline struct ZlangObject *AscensionType( struct ZlangRuntime *rt , struct ZlangObject *ascen_obj , struct ZlangObject *target_obj )
{
	struct ZlangObject	*tostr_obj = NULL ;
	char			*str = NULL ;
	int			str_len ;
	struct ZlangObject	*new_ascen_obj = NULL ;
	
	int			nret = 0 ;
	
	nret = ToString( rt , ascen_obj , & tostr_obj ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "obj[%s] ->to_string_ptr_func failed[%d]" , ascen_obj->obj_name , nret )
		return NULL;
	}
	
	nret = GetDataPtr( rt , tostr_obj , (void**) & str , & str_len ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "obj[%s] ->get_data_ptr_func failed[%d]" , tostr_obj->obj_name , nret )
		return NULL;
	}
	
	new_ascen_obj = CloneObjectInTmpStack( rt , NULL , target_obj ) ;
	if( new_ascen_obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CreateObjectInTmpStack for copy failed" )
		return NULL;
	}
	
	nret = FromCharPtr( rt , new_ascen_obj , str , str_len ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "copied obj[%s] ->from_char_ptr_func([%d][%.*s]) failed[%d]" , ascen_obj->obj_name , str_len , str_len,str , nret )
		return NULL;
	}
	
	return new_ascen_obj;
}

int TryAscensionType( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject **ascen_obj )
{
	struct ZlangObject	*new_ascen_obj = NULL ;
	
	if(	obj->funcs_enti->direct_funcs == rt->frequent_objs.short_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.ushort_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.int_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.uint_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.long_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.ulong_obj->funcs_enti->direct_funcs )
	{
		if(	(*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.short_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.ushort_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.int_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.uint_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.long_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.ulong_obj->funcs_enti->direct_funcs )
		{
			if( obj->funcs_enti->direct_funcs != (*ascen_obj)->funcs_enti->direct_funcs )
			{
				new_ascen_obj = AscensionType( rt , (*ascen_obj) , obj ) ;
				if( new_ascen_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AscensionType obj[%s] to clone_obj[%s] failed" , (*ascen_obj)->obj_name , obj->clone_obj_name )
					return GET_RUNTIME_ERROR_NO(rt);
				}
				(*ascen_obj) = new_ascen_obj ;
				return 2;
			}
		}
	}
	
	if(	obj->funcs_enti->direct_funcs == rt->frequent_objs.float_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.double_obj->funcs_enti->direct_funcs )
	{
		if(	(*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.float_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.double_obj->funcs_enti->direct_funcs )
		{
			if( obj->funcs_enti->direct_funcs != (*ascen_obj)->funcs_enti->direct_funcs )
			{
				new_ascen_obj = AscensionType( rt , (*ascen_obj) , obj ) ;
				if( new_ascen_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AscensionType obj[%s] to clone_obj[%s] failed" , (*ascen_obj)->obj_name , obj->clone_obj_name )
					return GET_RUNTIME_ERROR_NO(rt);
				}
				(*ascen_obj) = new_ascen_obj ;
				return 2;
			}
		}
	}
	
	if(	obj->funcs_enti->direct_funcs == rt->frequent_objs.float_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.double_obj->funcs_enti->direct_funcs )
	{
		if(	(*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.short_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.ushort_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.int_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.uint_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.long_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.ulong_obj->funcs_enti->direct_funcs )
		{
			new_ascen_obj = AscensionType( rt , (*ascen_obj) , obj ) ;
			if( new_ascen_obj == NULL )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AscensionType obj[%s] to clone_obj[%s] failed" , (*ascen_obj)->obj_name , obj->clone_obj_name )
				return GET_RUNTIME_ERROR_NO(rt);
			}
			(*ascen_obj) = new_ascen_obj ;
			return 2;
		}
	}
	
	if(	obj->funcs_enti->direct_funcs == rt->frequent_objs.short_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.ushort_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.int_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.uint_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.long_obj->funcs_enti->direct_funcs
		|| obj->funcs_enti->direct_funcs == rt->frequent_objs.ulong_obj->funcs_enti->direct_funcs )
	{
		if(	(*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.float_obj->funcs_enti->direct_funcs
			|| (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.double_obj->funcs_enti->direct_funcs )
		{
			new_ascen_obj = AscensionType( rt , (*ascen_obj) , obj ) ;
			if( new_ascen_obj == NULL )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AscensionType obj[%s] to clone_obj[%s] failed" , (*ascen_obj)->obj_name , obj->clone_obj_name )
				return GET_RUNTIME_ERROR_NO(rt);
			}
			(*ascen_obj) = new_ascen_obj ;
			return 2;
		}
	}
	
	return 0;
}

int TryAscensionType2( struct ZlangRuntime *rt , struct ZlangObject **ascen_obj , struct ZlangObject **ascen_obj2 )
{
	struct ZlangObject	**pp_ascen_obj = NULL ;
	struct ZlangObject	**pp_ascen_obj2 = NULL ;
	struct ZlangObject	*new_ascen_obj = NULL ;
	struct ZlangObject	*new_ascen_obj2 = NULL ;
	
	TEST_CHECKING(rt)
	{
		if( (*ascen_obj)->funcs_enti == NULL )
		{
			if( (*ascen_obj2)->funcs_enti == NULL )
			{
				return 1;
			}
			else
			{
				new_ascen_obj = AscensionType( rt , (*ascen_obj) , (*ascen_obj2) ) ;
				if( new_ascen_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AscensionType obj[%s] to clone_obj[%s] failed" , (*ascen_obj)->obj_name , (*ascen_obj2)->clone_obj_name )
					return GET_RUNTIME_ERROR_NO(rt);
				}
				(*ascen_obj) = new_ascen_obj ;
				return 1;
			}
		}
		else
		{
			if( (*ascen_obj2)->funcs_enti == NULL )
			{
				new_ascen_obj2 = AscensionType( rt , (*ascen_obj2) , (*ascen_obj) ) ;
				if( new_ascen_obj2 == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AscensionType obj[%s] to clone_obj[%s] failed" , (*ascen_obj2)->obj_name , (*ascen_obj)->clone_obj_name )
					return GET_RUNTIME_ERROR_NO(rt);
				}
				(*ascen_obj2) = new_ascen_obj2 ;
				return 2;
			}
			else
			{
				return 2;
			}
		}
	}
	
	if( (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.short_obj->funcs_enti->direct_funcs )
		pp_ascen_obj = & (rt->frequent_objs.short_obj) ;
	else if( (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.ushort_obj->funcs_enti->direct_funcs )
		pp_ascen_obj = & (rt->frequent_objs.ushort_obj) ;
	else if( (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.int_obj->funcs_enti->direct_funcs )
		pp_ascen_obj = & (rt->frequent_objs.int_obj) ;
	else if( (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.uint_obj->funcs_enti->direct_funcs )
		pp_ascen_obj = & (rt->frequent_objs.uint_obj) ;
	else if( (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.long_obj->funcs_enti->direct_funcs )
		pp_ascen_obj = & (rt->frequent_objs.long_obj) ;
	else if( (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.ulong_obj->funcs_enti->direct_funcs )
		pp_ascen_obj = & (rt->frequent_objs.ulong_obj) ;
	else if( (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.float_obj->funcs_enti->direct_funcs )
		pp_ascen_obj = & (rt->frequent_objs.float_obj) ;
	else if( (*ascen_obj)->funcs_enti->direct_funcs == rt->frequent_objs.double_obj->funcs_enti->direct_funcs )
		pp_ascen_obj = & (rt->frequent_objs.double_obj) ;
	
	if( (*ascen_obj2)->funcs_enti->direct_funcs == rt->frequent_objs.short_obj->funcs_enti->direct_funcs )
		pp_ascen_obj2 = & (rt->frequent_objs.short_obj) ;
	else if( (*ascen_obj2)->funcs_enti->direct_funcs == rt->frequent_objs.ushort_obj->funcs_enti->direct_funcs )
		pp_ascen_obj2 = & (rt->frequent_objs.ushort_obj) ;
	else if( (*ascen_obj2)->funcs_enti->direct_funcs == rt->frequent_objs.int_obj->funcs_enti->direct_funcs )
		pp_ascen_obj2 = & (rt->frequent_objs.int_obj) ;
	else if( (*ascen_obj2)->funcs_enti->direct_funcs == rt->frequent_objs.uint_obj->funcs_enti->direct_funcs )
		pp_ascen_obj2 = & (rt->frequent_objs.uint_obj) ;
	else if( (*ascen_obj2)->funcs_enti->direct_funcs == rt->frequent_objs.long_obj->funcs_enti->direct_funcs )
		pp_ascen_obj2 = & (rt->frequent_objs.long_obj) ;
	else if( (*ascen_obj2)->funcs_enti->direct_funcs == rt->frequent_objs.ulong_obj->funcs_enti->direct_funcs )
		pp_ascen_obj2 = & (rt->frequent_objs.ulong_obj) ;
	else if( (*ascen_obj2)->funcs_enti->direct_funcs == rt->frequent_objs.float_obj->funcs_enti->direct_funcs )
		pp_ascen_obj2 = & (rt->frequent_objs.float_obj) ;
	else if( (*ascen_obj2)->funcs_enti->direct_funcs == rt->frequent_objs.double_obj->funcs_enti->direct_funcs )
		pp_ascen_obj2 = & (rt->frequent_objs.double_obj) ;
	
	if( pp_ascen_obj && pp_ascen_obj2 )
	{
		if( (*pp_ascen_obj) < (*pp_ascen_obj2) )
		{
			new_ascen_obj = AscensionType( rt , (*ascen_obj) , (*ascen_obj2) ) ;
			if( new_ascen_obj == NULL )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AscensionType obj[%s] to clone_obj[%s] failed" , (*ascen_obj)->obj_name , (*ascen_obj2)->clone_obj_name )
				return GET_RUNTIME_ERROR_NO(rt);
			}
			(*ascen_obj) = new_ascen_obj ;
			return 1;
		}
		else if( (*pp_ascen_obj) > (*pp_ascen_obj2) )
		{
			new_ascen_obj2 = AscensionType( rt , (*ascen_obj2) , (*ascen_obj) ) ;
			if( new_ascen_obj2 == NULL )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AscensionType obj[%s] to clone_obj[%s] failed" , (*ascen_obj2)->obj_name , (*ascen_obj)->clone_obj_name )
				return GET_RUNTIME_ERROR_NO(rt);
			}
			(*ascen_obj2) = new_ascen_obj2 ;
			return 2;
		}
	}
	
	return 0;
}

int EvalObjectDirectProperty( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *copy_obj )
{
	void			*data = NULL ;
	int32_t			data_len ;
	int			nret = 0 ;
	
	if( obj == NULL || copy_obj == NULL )
		return 0;
	
	if( copy_obj->props_enti == NULL )
	{
		if( obj->props_enti )
		{
			if( obj->props_enti->direct_prop )
			{
				nret = DestroyObjectDirectProperty( rt , obj ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "DestroyObjectDirectProperty failed[%d]" , nret )
					return nret;
				}
			}
			
			UnreferObjectPropertiesEntity( rt , obj );
		}
	}
	else
	{
		if( obj->props_enti == NULL )
		{
			if( obj->funcs_enti == NULL )
			{
				nret = InitObject( rt , obj , obj->obj_name , GetObjectDirectFunctions(copy_obj) , (copy_obj->props_enti->direct_prop==NULL?ZLANG_INITOPTIONS_NO_CREATE_DIRECTPROPERTY:0) ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InitObject failed[%d]" , nret )
					return nret;
				}
			}
			else
			{
				nret = CreateObjectDirectProperty( rt , obj ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CreateObjectDirectProperty failed[%d]" , nret )
					return nret;
				}
			}
		}
	}
	
	if( copy_obj->funcs_enti == NULL || copy_obj->funcs_enti->direct_funcs == NULL || copy_obj->funcs_enti->direct_funcs->get_data_ptr_func == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "copy object no get_data_ptr_func" )
		return 0;
	}
	
	if( obj->funcs_enti == NULL || obj->funcs_enti->direct_funcs == NULL || obj->funcs_enti->direct_funcs->from_data_ptr_func == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "obj no from_data_ptr_func" )
		return 0;
	}
	
	if( ! IsTypeOf( rt , obj , copy_obj ) )
	{
		nret = TryAscensionType( rt , obj , & copy_obj ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s][%s] type not matched with right obj[%s][%s] type" , GetCloneObjectName(obj) , GetObjectName(obj) , GetCloneObjectName(copy_obj) , GetObjectName(copy_obj) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType " ); DebugPrintObject(rt,copy_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType copy_obj[%s] failed" , GetObjectName(copy_obj) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	nret = GetDataPtr( rt , copy_obj , & data , & data_len );
	if( nret )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_GET_DATA_PTR , "get data ptr failed" )
		return ZLANG_ERROR_GET_DATA_PTR;
	}
	
	if( data )
	{
		nret = FromDataPtr( rt , obj , data , data_len );
		if( nret )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_FROM_DATA_PTR , "from data ptr failed" )
			return ZLANG_ERROR_FROM_DATA_PTR;
		}
	}
	
	return 0;
}

int EvalObjectProperties( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *eval_obj )
{
	struct ZlangObject	*eval_obj_prop = NULL ;
	struct ZlangObject	o ;
	struct ZlangObject	*obj_prop = NULL ;
	int			nret = 0 ;
	
	for( eval_obj_prop = NULL ; ( eval_obj_prop = TravelPropertyFromEntityPropertiesTreeByPropertyName( eval_obj->props_enti , eval_obj_prop ) ) ; )
	{
		memset( & o , 0x00 , sizeof(struct ZlangObject) );
		o.obj_name = eval_obj_prop->obj_name ;
		obj_prop = QueryPropertyInEntityPropertiesTreeByPropertyName( obj->props_enti , & o ) ;
		if( obj_prop && ! obj_prop->is_constant )
		{
			nret = EvalObject( rt , obj_prop , eval_obj_prop ) ;
			if( nret )
				return nret;
		}
	}
	
	return 0;
}

int CopyObjectProperties( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *copy_obj )
{
	struct ZlangObject	*copy_obj_prop = NULL ;
	struct ZlangObject	o ;
	struct ZlangObject	*obj_prop = NULL ;
	int			nret = 0 ;
	
	if( copy_obj->props_enti == NULL )
		return 0;
	
	if( obj->funcs_enti == NULL )
	{
		obj->funcs_enti = AllocFunctionsEntity( rt ) ;
		if( obj->funcs_enti == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	if( obj->props_enti == NULL && obj->funcs_enti )
	{
		nret = CreateObjectDirectProperty( rt , obj ) ;
		if( nret )
			return nret;
	}
	
	list_for_each_entry( copy_obj_prop , & (copy_obj->props_enti->props_list) , struct ZlangObject , obj_list_node )
	{
		memset( & o , 0x00 , sizeof(struct ZlangObject) );
		o.obj_name = copy_obj_prop->obj_name ;
		obj_prop = QueryPropertyInEntityPropertiesTreeByPropertyName( obj->props_enti , & o ) ;
		if( obj_prop == NULL )
		{
			nret = CloneObject( rt , & obj_prop , copy_obj_prop->obj_name , copy_obj_prop ) ;
			if( nret )
				return nret;
			obj_prop->intercept_set = copy_obj_prop->intercept_set ;
			obj_prop->intercept_get = copy_obj_prop->intercept_get ;
			
			LinkPropertyToEntityPropertiesTreeByPropertyName( obj->props_enti , obj_prop );
			
			list_add_tail( & (obj_prop->obj_list_node) , & (obj->props_enti->props_list) );
		}
	}
	
	return 0;
}

int AddFunctionToObjectFunctionsEntity( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangFunction *func )
{
	int		nret = 0 ;
	
	if( obj->funcs_enti == NULL )
	{
		obj->funcs_enti = AllocFunctionsEntity( rt ) ;
		if( obj->funcs_enti == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	nret = LinkFunctionToFunctionsEntityFunctionsTreeByFunctionName( obj->funcs_enti , func ) ;
	if( nret )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_LINK_FUNC_TO_ENTITY , "link function func_name[%s] in funcs_enti[%p][%s] failed" , func->func_name , obj->funcs_enti,obj->funcs_enti->direct_funcs?obj->funcs_enti->direct_funcs->type_name:NULL )
		return ZLANG_ERROR_LINK_FUNC_TO_ENTITY;
	}
	
	nret = LinkFunctionToFunctionsEntityFunctionsTreeByFullFunctionName( obj->funcs_enti , func ) ;
	if( nret )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_LINK_FUNC_TO_ENTITY , "link function full_func_name[%s] in funcs_enti[%p][%s] failed" , func->full_func_name , obj->funcs_enti,obj->funcs_enti->direct_funcs?obj->funcs_enti->direct_funcs->type_name:NULL )
		return ZLANG_ERROR_LINK_FUNC_TO_ENTITY;
	}
	
	return 0;
}

int UnreferFunctionsEntity( struct ZlangRuntime *rt , struct ZlangFunctionsEntity *funcs_enti )
{
	if( funcs_enti == NULL )
		return 0;
	
	FreeFunctionsEntity( rt , funcs_enti );
	
	return 0;
}

int CloneObject( struct ZlangRuntime *rt , struct ZlangObject **pp_obj , char *obj_name , struct ZlangObject *clone_obj )
{
	struct ZlangObject		*obj = NULL ;
	
	int				nret = 0 ;
	
	if( pp_obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_INTERNAL , "internal error" )
		return ZLANG_ERROR_INTERNAL;
	}
	
	if( (*pp_obj) == NULL )
	{
		obj = AllocObject( rt ) ;
		if( obj == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for object" )
			return GET_RUNTIME_ERROR_NO(rt);
		}
		memset( obj , 0x00 , sizeof(struct ZlangObject) );
		
		nret = SetObjectName( rt , obj , obj_name ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SetObjectName failed[%d]" , nret )
			return nret;
		}
	}
	else
	{
		obj = (*pp_obj) ;
		
		nret = SetObjectName( rt , obj , obj_name ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SetObjectName failed[%d]" , nret )
			return nret;
		}
		
		nret = UnreferObject( rt , obj ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "UnreferObject failed[%d]" , nret )
			return nret;
		}
	}
	
	if( clone_obj )
	{
		SetObjectEmbellishName( rt , obj , GetObjectEmbellishName(clone_obj) );
		SetObjectEmbellishName2( rt , obj , GetObjectEmbellishName2(clone_obj) );
		
		obj->access_qualifier = clone_obj->access_qualifier ;
		// obj->is_constant = clone_obj->is_constant ;
		
		nret = ReferObjectFunctionsEntity( rt , obj , clone_obj ) ;
		if( nret )
		{
			if( pp_obj == NULL )
				FreeObject( rt , obj );
			return nret;
		}
		
		if( clone_obj->props_enti )
		{
			nret = EvalObjectDirectProperty( rt , obj , clone_obj ) ;
			if( nret )
			{
				if( pp_obj == NULL )
					FreeObject( rt , obj );
				return GET_RUNTIME_ERROR_NO(rt);
			}
			
			nret = CopyObjectProperties( rt , obj , clone_obj ) ;
			if( nret )
			{
				if( pp_obj == NULL )
					FreeObject( rt , obj );
				return GET_RUNTIME_ERROR_NO(rt);
			}
		}
	}
	
	if( pp_obj )
		(*pp_obj) = obj ;
	return 0;
}

struct ZlangObject *CloneZObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.zobject_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneStringObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.string_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneBoolObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.bool_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneShortObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.short_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneUShortObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.ushort_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneIntObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.int_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneUIntObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.uint_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneLongObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.long_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneULongObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.ulong_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneFloatObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.float_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneDoubleObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.double_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneArrayObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.array_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneListObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.list_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneListNodeObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.list_node_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneMapObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.map_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneIteratorObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.iterator_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneFunctionPtrObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	nret = CloneObject( rt , & obj , obj_name , rt->frequent_objs.functionptr_obj ) ;
	if( nret )
		return NULL;
	
	return obj;
}

struct ZlangObject *CloneNullObject( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	*obj = NULL ;
	int			nret = 0 ;
	
	obj = AllocObject( rt ) ;
	if( obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for object" )
		return NULL;
	}
	memset( obj , 0x00 , sizeof(struct ZlangObject) );
	
	nret = CloneObject( rt , & obj , obj_name , NULL ) ;
	if( nret )
	{
		FreeObject( rt , obj );
		return NULL;
	}
	
	return obj;
}

int EvalObject( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *eval_obj )
{
	int		nret = 0 ;
	
	if( GetObjectDirectFunctions(obj) == NULL && GetObjectDirectFunctions(eval_obj) )
	{
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InitObject on obj->funcs_enti==NULL and eval_obj->funcs_enti " ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		nret = InitObject( rt , obj , obj->obj_name , eval_obj->funcs_enti->direct_funcs , (IsObjectPropertiesEntityNull(eval_obj)?ZLANG_INITOPTIONS_NO_CREATE_DIRECTPROPERTY:0) ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InitObject failed[%d] , " , nret ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			return nret;
		}
		else
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InitObject ok , " ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		
		if( IsObjectPropertiesEntityNull(eval_obj) )
			return 0;
	}
	else if( GetObjectPropertiesEntity(obj) == NULL && GetObjectPropertiesEntity(eval_obj) )
	{
		if( GetObjectDirectFunctions(obj) == NULL )
		{
			nret = InitObject( rt , obj , obj->obj_name , eval_obj->funcs_enti->direct_funcs , 0 ) ;
			if( nret )
			{
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InitObject failed[%d] , " , nret ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				return nret;
			}
			else
			{
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InitObject ok , " ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			}
		}
		
		if( GetObjectPropertiesEntity(obj) == NULL )
		{
			nret = InitObject( rt , obj , obj->obj_name , obj->funcs_enti->direct_funcs , 0 ) ;
			if( nret )
			{
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InitObject failed[%d] , " , nret ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				return nret;
			}
			else
			{
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "InitObject ok , " ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			}
		}
		
		if( ! IsTypeOf( rt , obj , eval_obj ) )
		{
			nret = TryAscensionType( rt , obj , & eval_obj ) ;
			if( nret == 0 )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->type_name[%s] type not matched with right obj[%s]->type_name[%s] type" , GetObjectName(obj) , GetCloneObjectName(obj) , GetObjectName(eval_obj) , GetCloneObjectName(eval_obj) )
				return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
			}
			else if( nret == 2 )
			{
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType " ); DebugPrintObject(rt,eval_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			}
			else
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(obj) , GetObjectName(eval_obj) )
				return GET_RUNTIME_ERROR_NO(rt);
			}
		}
	}
	else
	{
		if( obj->is_constant )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT , "can't copy to a constant" )
			return ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT;
		}
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( eval_obj ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_SET_PROPERTY( obj , eval_obj ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptSetProperty failed[%d]" , nret )
		return nret; )

	nret = EvalObjectDirectProperty( rt , obj , eval_obj ) ;
	if( nret < 0 )
	{
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "EvalObjectDirectProperty failed[%d] , obj " , nret ); DebugPrintObject(rt,obj); printf( " , eval_obj " ); DebugPrintObject(rt,eval_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		return nret;
	}
	else
	{
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "EvalObjectDirectProperty ok , obj " ); DebugPrintObject(rt,obj); printf( " , eval_obj " ); DebugPrintObject(rt,eval_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	}
	
	nret = EvalObjectProperties( rt , obj , eval_obj ) ;
	if( nret < 0 )
	{
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "EvalObjectProperties failed[%d] , obj " , nret ); DebugPrintObject(rt,obj); printf( " , eval_obj " ); DebugPrintObject(rt,eval_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		return nret;
	}
	else
	{
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "EvalObjectProperties ok , obj " ); DebugPrintObject(rt,obj); printf( " , eval_obj " ); DebugPrintObject(rt,eval_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	}
	
	obj->access_qualifier = eval_obj->access_qualifier ;
	
	return 0;
}

int ReferObjectFunctionsEntity( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *refer_obj )
{
	int		nret = 0 ;
	
	if( obj->funcs_enti == refer_obj->funcs_enti )
		return 0;
	
	UnreferObjectFunctionsEntity( rt , obj );
	
	if( refer_obj && refer_obj->funcs_enti )
	{
		obj->funcs_enti = refer_obj->funcs_enti ;
#if defined(__linux__)
		__sync_add_and_fetch( & (obj->funcs_enti->refer_count) , 1 );
#elif defined(_WIN32)
		InterlockedIncrement( & (obj->funcs_enti->refer_count) );
#endif
		
		nret = SetCloneObjectName( rt , obj , GetCloneObjectName(refer_obj) ) ;
		if( nret )
			return nret;
		
		SetObjectEmbellishName( rt , obj , refer_obj->embellish_name );
		SetObjectEmbellishName2( rt , obj , refer_obj->embellish2_name );
	}
	else
	{
		FreeFunctionsEntity( rt , obj->funcs_enti );
		obj->funcs_enti = NULL ;
		
		SetCloneObjectName( rt , obj , NULL );
		
		SetObjectEmbellishName( rt , obj , NULL );
		SetObjectEmbellishName2( rt , obj , NULL );
	}
	
	return 0;
}

int UnreferObjectFunctionsEntity( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	int		nret = 0 ;
	
	if( obj->funcs_enti )
	{
		nret = UnreferFunctionsEntity( rt , obj->funcs_enti ) ;
		if( nret )
			return nret;
		obj->funcs_enti = NULL ;
		
		SetCloneObjectName( rt , obj , NULL );
	}
	
	return 0;
}

int ReferObjectPropertiesEntity( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *refer_obj )
{
	int		nret = 0 ;
	
	if( refer_obj->funcs_enti == NULL && refer_obj->props_enti == NULL )
	{
		return UnreferObject( rt , obj );
	}
	else if( ( obj->funcs_enti == NULL || obj->funcs_enti->direct_funcs == NULL ) && refer_obj->funcs_enti && refer_obj->funcs_enti->direct_funcs )
	{
		return ReferObjectFunctionsEntity( rt , obj , refer_obj );
	}
	else if( obj->funcs_enti && refer_obj->funcs_enti )
	{
		if( obj->props_enti )
		{
			if( obj->is_constant )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT , "can't copy to a constant" )
				return ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT;
			}
		}
		
		if( obj->funcs_enti->direct_funcs && refer_obj->funcs_enti->direct_funcs && obj->funcs_enti->direct_funcs != refer_obj->funcs_enti->direct_funcs )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_CANNOT_REFER_WITH_OTHER_TYPE_VALUE , "can't refer with other type value" )
			return ZLANG_ERROR_CANNOT_REFER_WITH_OTHER_TYPE_VALUE;
		}
	}
	
	UnreferObjectPropertiesEntity( rt , obj );
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( refer_obj ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_SET_PROPERTY( obj , refer_obj ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptSetProperty failed[%d]" , nret )
		return nret; )

	if( refer_obj->props_enti )
	{
		obj->props_enti = refer_obj->props_enti ;
#if defined(__linux__)
		__sync_add_and_fetch( & (obj->props_enti->refer_count) , 1 );
#elif defined(_WIN32)
		InterlockedIncrement( & (obj->props_enti->refer_count) );
#endif
	}
	else
	{
		obj->props_enti = NULL ;
	}
	
	return 0;
}

int UnreferObjectPropertiesEntity( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	if( obj->props_enti )
	{
		FreePropertiesEntity( rt , obj , obj->props_enti ); obj->props_enti = NULL ;
	}
	
	return 0;
}

int ReferObject( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *refer_obj )
{
	int		nret = 0 ;
	
	if( refer_obj == NULL )
	{
		UnreferObject( rt , obj );
		return 0;
	}
	else if( obj->funcs_enti == NULL )
	{
		if( refer_obj->funcs_enti )
		{
			ReferObjectFunctionsEntity( rt , obj , refer_obj );
		}
			
		nret = ReferObjectPropertiesEntity( rt , obj , refer_obj ) ;
		if( nret )
			return nret;
	}
	else if( obj->props_enti == NULL )
	{
		if( obj->is_constant )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_CANNOT_REFER_TO_A_CONSTANT , "can't refer to a constant" )
			return ZLANG_ERROR_CANNOT_REFER_TO_A_CONSTANT;
		}
		
		if( refer_obj->funcs_enti == NULL )
		{
			UnreferObjectFunctionsEntity( rt , obj );
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "UnreferObjectFunctionsEntity " ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			if( refer_obj->props_enti == NULL )
			{
				;
			}
			else
			{
				if( GetCloneObjectName(obj) == NULL )
				{
					nret = ReferObjectFunctionsEntity( rt , obj , refer_obj ) ;
					if( nret )
						return nret;
				}
				else
				{
					if( ! IsTypeOf( rt , obj , refer_obj ) )
					{
						nret = TryAscensionType( rt , obj , & refer_obj ) ;
						if( nret == 0 )
						{
							SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->type_name[%s] type not matched with right obj[%s]->type_name[%s] type" , GetObjectName(obj) , GetCloneObjectName(obj) , GetObjectName(refer_obj) , GetCloneObjectName(refer_obj) )
							return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
						}
						else if( nret == 2 )
						{
							TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType " ); DebugPrintObject(rt,refer_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
						}
						else
						{
							TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(obj) , GetObjectName(refer_obj) )
							return GET_RUNTIME_ERROR_NO(rt);
						}
					}
				}
				
				nret = ReferObjectPropertiesEntity( rt , obj , refer_obj ) ;
				if( nret )
					return nret;
				TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "ReferObject " ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
			}
		}
	}
	else
	{
		if( refer_obj->props_enti == NULL )
		{
			UnreferObjectPropertiesEntity( rt , obj );
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "UnreferObject " ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			if( ! IsTypeOf( rt , obj , refer_obj ) )
			{
				nret = TryAscensionType( rt , obj , & refer_obj ) ;
				if( nret == 0 )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->type_name[%s] type not matched with right obj[%s]->type_name[%s] type" , GetObjectName(obj) , GetCloneObjectName(obj) , GetObjectName(refer_obj) , GetCloneObjectName(refer_obj) )
					return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
				}
				else if( nret == 2 )
				{
					TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType " ); DebugPrintObject(rt,refer_obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
				}
				else
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(obj) , GetObjectName(refer_obj) )
					return GET_RUNTIME_ERROR_NO(rt);
				}
			}
			
			nret = ReferObjectPropertiesEntity( rt , obj , refer_obj ) ;
			if( nret )
				return nret;
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "ReferObject " ); DebugPrintObject(rt,obj); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
	}
	
	return 0;
}

int UnreferObject( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	UnreferObjectPropertiesEntity( rt , obj );
	
	UnreferObjectFunctionsEntity( rt , obj );
	
	return 0;
}

int CreateObjectDirectProperty( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	if( obj->props_enti == NULL )
	{
		obj->props_enti = AllocPropertiesEntity( rt ) ;
		if( obj->props_enti == NULL )
		{
			CleanObject( rt , obj );
			return ZLANG_ERROR_ALLOC;
		}
		
		INIT_LIST_HEAD( & (obj->props_enti->props_list) );
	}
	
	if( obj->props_enti->direct_prop )
		return 0;
	
	if( obj->funcs_enti && obj->funcs_enti->direct_funcs && obj->funcs_enti->direct_funcs->create_direct_prop_func )
	{
		obj->props_enti->direct_prop = obj->funcs_enti->direct_funcs->create_direct_prop_func( rt , obj ) ;
		if( obj->props_enti->direct_prop == NULL )
		{
			return ZLANG_ERROR_CREATE_OBJECT;
		}
	}
	
	return 0;
}

int DestroyObjectDirectProperty( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	if( obj->props_enti->direct_prop == NULL )
		return 0;
	
	if( obj->funcs_enti->direct_funcs && obj->funcs_enti->direct_funcs->destroy_direct_prop_func )
	{
		obj->funcs_enti->direct_funcs->destroy_direct_prop_func( rt , obj );
		ZLFREE( obj->props_enti->direct_prop ); obj->props_enti->direct_prop = NULL ;
	}
	
	return 0;
}

int InitObject( struct ZlangRuntime *rt , struct ZlangObject *obj , char *obj_name , struct ZlangDirectFunctions *direct_funcs , uint64_t init_options )
{
	int		nret = 0 ;
	
	if( obj == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_PARAMETER , "InitObject parameter obj[%p]" , obj )
		return ZLANG_ERROR_PARAMETER;
	}
	
	nret = SetObjectName( rt , obj , obj_name ) ;
	if( nret )
		return nret;
	
	nret = UnreferObject( rt , obj ) ;
	if( nret )
		return nret;
	
	if( direct_funcs )
	{
		if( obj->funcs_enti == NULL )
		{
			obj->funcs_enti = AllocFunctionsEntity( rt ) ;
			if( obj->funcs_enti == NULL )
				return GET_RUNTIME_ERROR_NO(rt);
		}
		
		if( direct_funcs != obj->funcs_enti->direct_funcs )
		{
			obj->funcs_enti->direct_funcs = direct_funcs ;
			nret = SetCloneObjectName( rt , obj , direct_funcs->type_name ) ;
			if( nret )
				return nret;
		}
	}
	
	if( ! TEST_ATTRIBUTE( init_options , ZLANG_INITOPTIONS_NO_CREATE_DIRECTPROPERTY ) )
	{
		nret = CreateObjectDirectProperty( rt , obj ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CreateObjectDirectProperty failed" )
			CleanObject( rt , obj );
			return nret;
		}
	}
	
	return 0;
}

void CleanObject( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	int		nret = 0 ;
	
	if( IsAtomicObject(obj) )
	{
		UnsetAtomicObject( obj );
	}
	
	nret = UnreferObject( rt , obj ) ;
	if( nret )
		return;
	
	SetObjectName( rt , obj , NULL );
	SetObjectEmbellishName( rt , obj , NULL );
	SetObjectEmbellishName2( rt , obj , NULL );
	
	return;
}

void DestroyObject( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	CleanObject( rt , obj );
	
	FreeObject( rt , obj );
	
	return;
}

int FromCharPtr( struct ZlangRuntime *rt , struct ZlangObject *obj , char *str , int32_t str_len )
{
	int		nret = 0 ;
	
	if( obj == NULL || obj->funcs_enti == NULL || obj->funcs_enti->direct_funcs == NULL || obj->funcs_enti->direct_funcs->from_char_ptr_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_FROMCHARPTR_FUNC_IN_OBJECT , "no FromCharPtr func in object[%p][%s]" , obj , obj->obj_name )
		return ZLANG_ERROR_NO_FROMCHARPTR_FUNC_IN_OBJECT;
	}
	
	if( GetObjectDirectProperty(obj) == NULL )
	{
		nret = InitObject( rt , obj , GetObjectName(obj) , GetObjectDirectFunctions(obj) , 0 ) ;
		if( nret )
			return nret;
	}
	
	return obj->funcs_enti->direct_funcs->from_char_ptr_func( rt , obj , str , str_len );
}

int ToString( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject **str_obj )
{
	int		nret = 0 ;
	
	if( obj->props_enti == NULL )
	{
		(*str_obj) = CloneObjectInTmpStack( rt , NULL , NULL ) ;
		if( (*str_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
		
		return 0;
	}
	
	if( (*str_obj) == NULL )
	{
		(*str_obj) = CloneStringObjectInTmpStack( rt , NULL ) ;
		if( (*str_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	if( obj->funcs_enti->direct_funcs->to_string_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_TOSTRING_FUNC_IN_OBJECT , "no ToString func in object[%s]" , obj->obj_name )
		return ZLANG_ERROR_NO_TOSTRING_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( obj ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	nret = obj->funcs_enti->direct_funcs->to_string_func( rt , obj , str_obj ) ;
	if( nret )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "->to_string_func failed[%d]" , nret )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	return 0;
}

int FromDataPtr( struct ZlangRuntime *rt , struct ZlangObject *obj , void *value , int32_t value_len )
{
	int		nret = 0 ;
	
	if( obj->funcs_enti->direct_funcs->from_data_ptr_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_FROMDATAPTR_FUNC_IN_OBJECT , "no FromDataPtr func in object[%s]" , obj->obj_name )
		return ZLANG_ERROR_NO_FROMDATAPTR_FUNC_IN_OBJECT;
	}
	
	if( GetObjectDirectProperty(obj) == NULL )
	{
		nret = InitObject( rt , obj , GetObjectName(obj) , GetObjectDirectFunctions(obj) , 0 ) ;
		if( nret )
			return nret;
	}
	
	if( obj->is_constant )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT , "can't copy to a constant" )
		return ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT;
	}
	
	return obj->funcs_enti->direct_funcs->from_data_ptr_func( rt , obj , value , value_len );
}

int GetDataPtr( struct ZlangRuntime *rt , struct ZlangObject *obj , void **value , int32_t *value_len )
{
	int		nret = 0 ;
	
	if( obj->props_enti == NULL )
	{
		if( value )
			(*value) = NULL ;
		if( value_len )
			(*value_len) = 0 ;
		
		return 0;
	}
	
	if( obj->funcs_enti->direct_funcs->get_data_ptr_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_GETDATAPTR_FUNC_IN_OBJECT , "no GetDataPtr func in object[%s]" , obj->obj_name )
		return ZLANG_ERROR_NO_GETDATAPTR_FUNC_IN_OBJECT;
	}
	
	if( GetObjectDirectProperty(obj) == NULL )
	{
		nret = InitObject( rt , obj , GetObjectName(obj) , GetObjectDirectFunctions(obj) , 0 ) ;
		if( nret )
			return nret;
	}
	
	return obj->funcs_enti->direct_funcs->get_data_ptr_func( rt , obj , value , value_len );
}

int Operator_PLUS( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1 == NULL || in_obj2 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_NULL , "oper invalid on null in object[%s] and object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_OPER_NULL;
	}
	
	if( IsTypeOf( rt , in_obj1 , GetStringObjectInRuntimeObjectsHeap(rt) ) && in_obj2->funcs_enti == NULL )
	{
		in_obj2 = CloneStringObject( rt , NULL ) ;
		if( in_obj2 == NULL )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneStringObject failed[%d]" , GET_RUNTIME_ERROR_NO(rt) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	else if( in_obj1->funcs_enti == NULL && IsTypeOf( rt , in_obj2 , GetStringObjectInRuntimeObjectsHeap(rt) ) )
	{
		in_obj1 = CloneStringObject( rt , NULL ) ;
		if( in_obj1 == NULL )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneStringObject failed[%d]" , GET_RUNTIME_ERROR_NO(rt) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	else if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->type_name[%s] type not matched with right obj[%s]->type_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_obj1->funcs_enti->direct_funcs->oper_PLUS_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_PLUS_FUNC_IN_OBJECT , "no oper PLUS func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_OPER_PLUS_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->oper_PLUS_func( rt , in_obj1 , in_obj2 , out_obj );
}

int Operator_MINUS( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1 == NULL || in_obj2 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_NULL , "oper invalid on null in object[%s] and object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_OPER_NULL;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->type_name[%s] type not matched with right obj[%s]->type_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_obj1->funcs_enti->direct_funcs->oper_MINUS_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_MINUS_FUNC_IN_OBJECT , "no oper MINUS func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_OPER_MINUS_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->oper_MINUS_func( rt , in_obj1 , in_obj2 , out_obj );
}

int Operator_MUL( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1 == NULL || in_obj2 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_NULL , "oper invalid on null in object[%s] and object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_OPER_NULL;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->ancestor_name[%s] type not matched with right obj[%s]->ancestor_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType2 obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_obj1->funcs_enti->direct_funcs->oper_MUL_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_MUL_FUNC_IN_OBJECT , "no oper MUL func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_OPER_MUL_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->oper_MUL_func( rt , in_obj1 , in_obj2 , out_obj );
}

int Operator_DIV( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1 == NULL || in_obj2 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_NULL , "oper invalid on null in object[%s] and object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_OPER_NULL;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->ancestor_name[%s] type not matched with right obj[%s]->ancestor_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_obj1->funcs_enti->direct_funcs->oper_DIV_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_DIV_FUNC_IN_OBJECT , "no oper DIV func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_OPER_DIV_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->oper_DIV_func( rt , in_obj1 , in_obj2 , out_obj );
}

int Operator_MOD( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1 == NULL || in_obj2 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_NULL , "oper invalid on null in object[%s] and object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_OPER_NULL;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->ancestor_name[%s] type not matched with right obj[%s]->ancestor_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_obj1->funcs_enti->direct_funcs->oper_MOD_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_OPER_MOD_FUNC_IN_OBJECT , "no oper MOD func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_OPER_MOD_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->oper_MOD_func( rt , in_obj1 , in_obj2 , out_obj );
}

int UnaryOperator_NEGATIVE( struct ZlangRuntime *rt , struct ZlangObject *in_out_obj1 )
{
	int		nret = 0 ;
	
	if( in_out_obj1 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_NULL , "unary invalid on null in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_NULL;
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_out_obj1->funcs_enti->direct_funcs->unaryoper_NEGATIVE_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_NEGATIVE_FUNC_IN_OBJECT , "no unaryoper NEGATIVE func in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_NEGATIVE_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_out_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_out_obj1->funcs_enti->direct_funcs->unaryoper_NEGATIVE_func( rt , in_out_obj1 );
}

int UnaryOperator_NOT( struct ZlangRuntime *rt , struct ZlangObject *in_out_obj1 )
{
	int		nret = 0 ;
	
	if( in_out_obj1 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_NULL , "unary invalid on null in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_NULL;
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_out_obj1->is_constant )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT , "can't copy to a constant" )
		return ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT;
	}
	
	if( in_out_obj1->funcs_enti->direct_funcs->unaryoper_NOT_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_NOT_FUNC_IN_OBJECT , "no unaryoper NOT func in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_NOT_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_out_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_out_obj1->funcs_enti->direct_funcs->unaryoper_NOT_func( rt , in_out_obj1 );
}

int UnaryOperator_BIT_REVERSE( struct ZlangRuntime *rt , struct ZlangObject *in_out_obj1 )
{
	int		nret = 0 ;
	
	if( in_out_obj1 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_NULL , "unary invalid on null in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_NULL;
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_out_obj1->funcs_enti->direct_funcs->unaryoper_NOT_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_BIT_REVERSE_FUNC_IN_OBJECT , "no unaryoper BIT REVERSE func in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_BIT_REVERSE_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_out_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_out_obj1->funcs_enti->direct_funcs->unaryoper_BIT_REVERSE_func( rt , in_out_obj1 );
}

int UnaryOperator_PLUS_PLUS( struct ZlangRuntime *rt , struct ZlangObject *in_out_obj1 )
{
	int		nret = 0 ;
	
	if( in_out_obj1 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_NULL , "unary invalid on null in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_NULL;
	}
	
	if( in_out_obj1->is_constant )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT , "can't copy to a constant" )
		return ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT;
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_out_obj1->funcs_enti->direct_funcs->unaryoper_PLUS_PLUS_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_PLUS_PLUS_FUNC_IN_OBJECT , "no unaryoper PLUS_PLUS func in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_PLUS_PLUS_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_out_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_out_obj1->funcs_enti->direct_funcs->unaryoper_PLUS_PLUS_func( rt , in_out_obj1 );
}

int UnaryOperator_MINUS_MINUS( struct ZlangRuntime *rt , struct ZlangObject *in_out_obj1 )
{
	int		nret = 0 ;
	
	if( in_out_obj1 == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_NULL , "unary invalid on null in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_NULL;
	}
	
	if( in_out_obj1->is_constant )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT , "can't copy to a constant" )
		return ZLANG_ERROR_CANNOT_COPY_TO_A_CONSTANT;
	}
	
	TEST_CHECKING(rt)
		return 0;
	
	if( in_out_obj1->funcs_enti->direct_funcs->unaryoper_MINUS_MINUS_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_UNARYOPER_MINUS_MINUS_FUNC_IN_OBJECT , "no unaryoper MINUS_MINUS func in object[%s]" , GetObjectName(in_out_obj1) )
		return ZLANG_ERROR_NO_UNARYOPER_MINUS_MINUS_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_out_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_out_obj1->funcs_enti->direct_funcs->unaryoper_MINUS_MINUS_func( rt , in_out_obj1 );
}

int Compare_EQUAL( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneBoolObjectInTmpStack( rt , NULL ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL , "obj[%s] type is't 'bool'" , GetObjectName(*out_obj) )
			return ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL;
		}
	}
	
	if( in_obj1->props_enti == NULL && in_obj2->props_enti == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%p]==[%p]=>[true]" , in_obj1->props_enti , in_obj2->props_enti );
		CallRuntimeFunction_bool_SetBoolValue( rt , (*out_obj) , TRUE );
		return 0;
	}
	else if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%p]==[%p]=>[false]" , in_obj1->props_enti , in_obj2->props_enti );
		CallRuntimeFunction_bool_SetBoolValue( rt , (*out_obj) , FALSE );
		return 0;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->ancestor_name[%s] type not matched with right obj[%s]->ancestor_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->comp_EGUAL_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_EGUAL_FUNC_IN_OBJECT , "no comp EGUAL func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_COMP_EGUAL_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->comp_EGUAL_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Compare_NOTEQUAL( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneBoolObjectInTmpStack( rt , NULL ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL , "obj[%s] type is't 'bool'" , GetObjectName(*out_obj) )
			return ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL;
		}
	}
	
	if( in_obj1->props_enti == NULL && in_obj2->props_enti == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%p]!=[%p]=>[false]" , in_obj1->props_enti , in_obj2->props_enti );
		CallRuntimeFunction_bool_SetBoolValue( rt , (*out_obj) , FALSE );
		return 0;
	}
	else if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "[%p]!=[%p]=>[true]" , in_obj1->props_enti , in_obj2->props_enti );
		CallRuntimeFunction_bool_SetBoolValue( rt , (*out_obj) , TRUE );
		return 0;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->ancestor_name[%s] type not matched with right obj[%s]->ancestor_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->comp_NOTEGUAL_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NOTEGUAL_FUNC_IN_OBJECT , "no comp NOTEGUAL func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_COMP_NOTEGUAL_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->comp_NOTEGUAL_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Compare_LT( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneBoolObjectInTmpStack( rt , NULL ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL , "obj[%s] type is't 'bool'" , GetObjectName(*out_obj) )
			return ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL;
		}
	}
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->ancestor_name[%s] type not matched with right obj[%s]->ancestor_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->comp_LT_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_LT_FUNC_IN_OBJECT , "no comp LT func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_COMP_LT_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->comp_LT_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Compare_LE( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneBoolObjectInTmpStack( rt , NULL ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL , "obj[%s] type is't 'bool'" , GetObjectName(*out_obj) )
			return ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL;
		}
	}
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->ancestor_name[%s] type not matched with right obj[%s]->ancestor_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->comp_LE_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_LE_FUNC_IN_OBJECT , "no comp LE func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_COMP_LE_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->comp_LE_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Compare_GT( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneBoolObjectInTmpStack( rt , NULL ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL , "obj[%s] type is't 'bool'" , GetObjectName(*out_obj) )
			return ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL;
		}
	}
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] or in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->ancestor_name[%s] type not matched with right obj[%s]->ancestor_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->comp_GT_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_GT_FUNC_IN_OBJECT , "no comp GT func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_COMP_GT_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->comp_GT_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Compare_GE( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneBoolObjectInTmpStack( rt , NULL ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL , "obj[%s] type is't 'bool'" , GetObjectName(*out_obj) )
			return ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL;
		}
	}
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if( ! IsTypeOf( rt , in_obj1 , in_obj2 ) )
	{
		nret = TryAscensionType2( rt , & in_obj1 , & in_obj2 ) ;
		if( nret == 0 )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "left obj[%s]->ancestor_name[%s] type not matched with right obj[%s]->ancestor_name[%s] type" , GetObjectName(in_obj1) , GetCloneObjectName(in_obj1) , GetObjectName(in_obj2) , GetCloneObjectName(in_obj2) )
			return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
		}
		else if( nret == 1 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 1 , " ); DebugPrintObject(rt,in_obj1); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else if( nret == 2 )
		{
			TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "TryAscensionType return 2 , " ); DebugPrintObject(rt,in_obj2); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		}
		else
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TryAscensionType obj[%s] and obj[%s] failed" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->comp_GE_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_GE_FUNC_IN_OBJECT , "no comp GE func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_COMP_GE_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->comp_GE_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Logic_AND( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneBoolObjectInTmpStack( rt , NULL ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL , "obj[%s] type is't 'bool'" , GetObjectName(*out_obj) )
			return ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL;
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->logic_AND_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_LOGIC_AND_FUNC_IN_OBJECT , "no logic AND func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_LOGIC_AND_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->logic_AND_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Logic_OR( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneBoolObjectInTmpStack( rt , NULL ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL , "obj[%s] type is't 'bool'" , GetObjectName(*out_obj) )
			return ZLANG_ERROR_OBJECT_TYPE_ISNOT_BOOL;
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->logic_OR_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_LOGIC_OR_FUNC_IN_OBJECT , "no logic OR func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_LOGIC_OR_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->logic_OR_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Bit_AND( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , in_obj1 ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_NOT_MATCHED , "obj[%s] type not matched with obj[%s]" , GetObjectName(*out_obj) , GetObjectName(in_obj1) )
			return ZLANG_ERROR_OBJECT_TYPE_NOT_MATCHED;
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->bit_AND_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_BIT_AND_FUNC_IN_OBJECT , "no bit AND func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_BIT_AND_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->bit_AND_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Bit_XOR( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , in_obj1 ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_NOT_MATCHED , "obj[%s] type not matched with obj[%s]" , GetObjectName(*out_obj) , GetObjectName(in_obj1) )
			return ZLANG_ERROR_OBJECT_TYPE_NOT_MATCHED;
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->bit_XOR_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_BIT_XOR_FUNC_IN_OBJECT , "no bit XOR func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_BIT_XOR_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->bit_XOR_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Bit_OR( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	else
	{
		if( ! IsTypeOf( rt , (*out_obj) , in_obj1 ) )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_TYPE_NOT_MATCHED , "obj[%s] type not matched with obj[%s]" , GetObjectName(*out_obj) , GetObjectName(in_obj1) )
			return ZLANG_ERROR_OBJECT_TYPE_NOT_MATCHED;
		}
	}
	
	if( in_obj1->funcs_enti->direct_funcs->bit_OR_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_BIT_OR_FUNC_IN_OBJECT , "no bit OR func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_BIT_OR_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->bit_OR_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Bit_MOVELEFT( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if(	(	IsTypeOf( rt , in_obj1 , GetShortObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetUShortObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetIntObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetUIntObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetLongObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetULongObjectInRuntimeObjectsHeap(rt) )
		)
		&&
		(	IsTypeOf( rt , in_obj2 , GetIntObjectInRuntimeObjectsHeap(rt) )
		)
	)
	{
		;
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "operator type not matched , left-obj[%s][%s] right-obj[%s][%s]" , GetCloneObjectName(in_obj1) , GetObjectName(in_obj1) , GetCloneObjectName(in_obj2) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	if( in_obj1->funcs_enti->direct_funcs->bit_MOVELEFT_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_BIT_MOVELEFT_FUNC_IN_OBJECT , "no bit MOVELEFT func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_BIT_OR_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->bit_MOVELEFT_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

int Bit_MOVERIGHT( struct ZlangRuntime *rt , struct ZlangObject *in_obj1 , struct ZlangObject *in_obj2 , struct ZlangObject **out_obj )
{
	int		nret = 0 ;
	
	if( in_obj1->props_enti == NULL || in_obj2->props_enti == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_COMP_NULL , "compare invalid on null in object[%s] in object[%s]" , GetObjectName(in_obj1) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_NO_COMP_NULL;
	}
	
	if(	(	IsTypeOf( rt , in_obj1 , GetShortObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetUShortObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetIntObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetUIntObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetLongObjectInRuntimeObjectsHeap(rt) )
			|| IsTypeOf( rt , in_obj1 , GetULongObjectInRuntimeObjectsHeap(rt) )
		)
		&&
		(	IsTypeOf( rt , in_obj2 , GetIntObjectInRuntimeObjectsHeap(rt) )
		)
	)
	{
		;
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED , "operator type not matched , left-obj[%s][%s] right-obj[%s][%s]" , GetCloneObjectName(in_obj1) , GetObjectName(in_obj1) , GetCloneObjectName(in_obj2) , GetObjectName(in_obj2) )
		return ZLANG_ERROR_OPERATOR_TYPE_NOT_MATCHED;
	}
	
	if( (*out_obj) == NULL )
	{
		(*out_obj) = CloneObjectInTmpStack( rt , NULL , in_obj1 ) ;
		if( (*out_obj) == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
	}
	
	if( in_obj1->funcs_enti->direct_funcs->bit_MOVERIGHT_func == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_NO_BIT_MOVELEFT_FUNC_IN_OBJECT , "no bit MOVERIGHTLEFT func in object[%s]" , GetObjectName(in_obj1) )
		return ZLANG_ERROR_NO_BIT_OR_FUNC_IN_OBJECT;
	}
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj1 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	CHECK_THEN_INTERCEPT_GET_PROPERTY( in_obj2 ,
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterceptGetProperty failed[%d]" , nret )
		return nret; )
	
	return in_obj1->funcs_enti->direct_funcs->bit_MOVERIGHT_func( rt , in_obj1 , in_obj2 , (*out_obj) );
}

#if 0
size_t GetObjectSize()
{
	return sizeof(struct ZlangObject);
}
#endif

struct ZlangPropertiesEntity *GetObjectPropertiesEntity( struct ZlangObject *obj )
{
	if( obj == NULL )
		return NULL;
	return obj->props_enti;
}

void *GetObjectDirectProperty( struct ZlangObject *obj )
{
	if( obj == NULL || obj->props_enti == NULL )
		return NULL;
	return obj->props_enti->direct_prop;
}

struct ZlangDirectFunctions *GetObjectDirectFunctions( struct ZlangObject *obj )
{
	if( obj == NULL || obj->funcs_enti == NULL )
		return NULL;
	return obj->funcs_enti->direct_funcs;
}

void SetObjectDirectFuncstions( struct ZlangObject *obj , struct ZlangDirectFunctions *direct_funcs )
{
	if( obj == NULL || obj->funcs_enti == NULL )
		return;
	obj->funcs_enti->direct_funcs = direct_funcs ;
	return;
}

struct ZlangFunctionsEntity *GetObjectFunctionsEntity( struct ZlangObject *obj )
{
	if( obj == NULL )
		return NULL;
	
	return obj->funcs_enti;
}

struct ZlangFunctionsEntity *GetObjectAncestorFunctionsEntity( struct ZlangObject *obj )
{
	if( obj == NULL || obj->funcs_enti == NULL )
		return NULL;
	
	return obj->funcs_enti->ancestor_funcs_enti;
}

int SetObjectAncestorFunctionsEntity( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangFunctionsEntity *set_funcs_enti )
{
	if( obj == NULL )
		return ZLANG_ERROR_INTERNAL;
	
	if( obj->funcs_enti == NULL )
	{
		obj->funcs_enti = AllocFunctionsEntity( rt ) ;
		if( obj->funcs_enti == NULL )
			return GetRuntimeErrorNo(rt);
	}
	
	if( set_funcs_enti )
	{
		obj->funcs_enti->ancestor_funcs_enti = set_funcs_enti ;
	}
	
	return 0;
}

struct ZlangFunctionsEntity *GetObjectAncestorAncestorFunctionsEntity( struct ZlangObject *obj )
{
	struct ZlangFunctionsEntity	*ancestor_funcs_enti = NULL ;
	
	if( obj == NULL || obj->funcs_enti == NULL )
		return NULL;
	
	ancestor_funcs_enti = obj->funcs_enti->ancestor_funcs_enti ;
	if( ancestor_funcs_enti == NULL )
		return NULL;
	while( ancestor_funcs_enti->ancestor_funcs_enti )
		ancestor_funcs_enti = ancestor_funcs_enti->ancestor_funcs_enti ;
	return ancestor_funcs_enti;
}

int SetObjectAncestorAncestorFunctionsEntity( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangFunctionsEntity *set_funcs_enti )
{
	struct ZlangFunctionsEntity	*ancestor_funcs_enti = NULL ;
	
	if( obj == NULL || obj->funcs_enti == NULL )
		return 0;
	
	ancestor_funcs_enti = obj->funcs_enti->ancestor_funcs_enti ;
	if( ancestor_funcs_enti == NULL )
	{
		obj->funcs_enti->ancestor_funcs_enti = set_funcs_enti ;
		return 0;
	}
	while( ancestor_funcs_enti->ancestor_funcs_enti )
		ancestor_funcs_enti = ancestor_funcs_enti->ancestor_funcs_enti ;
	ancestor_funcs_enti->ancestor_funcs_enti = set_funcs_enti ;
	return 0;
}

unsigned char IsTypeOf( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *type_obj )
{
	if( obj == NULL || type_obj == NULL )
		return 0;
	
	if( obj->funcs_enti && obj->clone_obj_name && type_obj->funcs_enti && type_obj->clone_obj_name && STRCMP( obj->clone_obj_name , == , type_obj->clone_obj_name ) )
		return 1;
	
	if( obj->funcs_enti && obj->funcs_enti->direct_funcs && type_obj->funcs_enti && type_obj->funcs_enti->direct_funcs && obj->funcs_enti->direct_funcs == type_obj->funcs_enti->direct_funcs )
		return 1;
	
	return 0;
}

void SetObjectAccessQualifier( struct ZlangObject *obj , unsigned char access_qualifier )
{
	obj->access_qualifier = access_qualifier ;
	return;
}

unsigned char GetObjectAccessQualifier( struct ZlangObject *obj )
{
	return obj->access_qualifier;
}

void SetConstantObject( struct ZlangObject *obj )
{
	obj->is_constant = 1 ;
	return;
}

void UnsetConstantObject( struct ZlangObject *obj )
{
	obj->is_constant = 0 ;
	return;
}

unsigned char IsConstantObject( struct ZlangObject *obj )
{
	if( obj == NULL )
		return 0;
	
	return obj->is_constant;
}

int SetAtomicObject( struct ZlangObject *obj )
{
#if defined(__linux__)
	pthread_mutexattr_t	attr ;
#elif defined(_WIN32)
#endif
	int			nret = 0 ;
	
	if( obj == NULL )
		return -1;
	
	if( obj->atomic_lock == NULL )
	{
		obj->atomic_lock = (struct ZlangMutexLock *)malloc( sizeof(struct ZlangMutexLock) ) ;
		if( obj->atomic_lock == NULL )
			return ZLANG_ERROR_ALLOC;
		memset( obj->atomic_lock , 0x00 , sizeof(struct ZlangMutexLock) );
		
#if defined(__linux__)
		pthread_mutexattr_init( & attr );
		pthread_mutexattr_settype( & attr , PTHREAD_MUTEX_RECURSIVE_NP );
		nret = pthread_mutex_init( & (obj->atomic_lock->lock) , & attr ) ;
		pthread_mutexattr_destroy( & attr );
#elif defined(_WIN32)
		InitializeCriticalSection( & (obj->atomic_lock->lock) );
#endif
		
#if defined(__linux__)
		__sync_add_and_fetch( & (obj->atomic_lock->refer_count) , 1 );
#elif defined(_WIN32)
		InterlockedIncrement( & (obj->atomic_lock->refer_count) );
#endif
	}
	
	return nret;
}

int UnsetAtomicObject( struct ZlangObject *obj )
{
	if( obj == NULL )
		return -1;
	
	if( obj->atomic_lock )
	{
#if defined(__linux__)
		if( __sync_sub_and_fetch( & (obj->atomic_lock->refer_count) , 1 ) == 0 )
		{
			pthread_mutex_destroy( & (obj->atomic_lock->lock) );
		}
#elif defined(_WIN32)
		if( InterlockedDecrement( & (obj->atomic_lock->refer_count) ) == 0 )
		{
			DeleteCriticalSection( & (obj->atomic_lock->lock) );
		}
#endif
		free( obj->atomic_lock ); obj->atomic_lock = NULL ;
	}
	
	return 0;
}

unsigned char IsAtomicObject( struct ZlangObject *obj )
{
	if( obj == NULL )
		return 0;
	
	return obj->atomic_lock?1:0;
}

int LockAtomicObject( struct ZlangObject *obj )
{
	int		nret = 0 ;
	
	if( obj == NULL )
		return -1;
	
	if( obj->atomic_lock )
	{
#if defined(__linux__)
		nret = pthread_mutex_lock( & (obj->atomic_lock->lock) ) ;
#elif defined(_WIN32)
		EnterCriticalSection( & (obj->atomic_lock->lock) );
		nret = 0 ;
#endif
	}
	
	return nret;
}

int UnlockAtomicObject( struct ZlangObject *obj )
{
	int		nret = 0 ;
	
	if( obj == NULL )
		return -1;
	
	if( obj->atomic_lock )
	{
#if defined(__linux__)
		nret = pthread_mutex_unlock( & (obj->atomic_lock->lock) ) ;
#elif defined(_WIN32)
		LeaveCriticalSection( & (obj->atomic_lock->lock) );
		nret = 0 ;
#endif
	}
	
	return nret;
}

void CopyAtomicLock( struct ZlangObject *obj , struct ZlangObject *copy_obj )
{
	if( IsAtomicObject(copy_obj) )
	{
		obj->atomic_lock = copy_obj->atomic_lock ;
#if defined(__linux__)
		__sync_add_and_fetch( & (obj->atomic_lock->refer_count) , 1 );
#elif defined(_WIN32)
		InterlockedIncrement( & (obj->atomic_lock->refer_count) );
#endif
	}
	
	return;
}

static int _SetObjectName( struct ZlangRuntime *rt , void *st , size_t offset_of_member , char *new_name )
{
	char		**name = NULL ;
	char		*tmp = NULL ;
	
	name = (char**)( (char*)st + offset_of_member ) ;
	if( new_name )
	{
		tmp = ZLSTRDUP( new_name ) ;
		if( tmp == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_STRDUP , "alloc memory for object name" )
			return ZLANG_ERROR_STRDUP;
		}
		
		if( (*name) )
			ZLFREE( (*name) );
		
		(*name) = tmp ;
	}
	else
	{
		if( (*name) )
			ZLFREE( (*name) );
		
		(*name) = NULL ;
	}
	
	return 0;
}

int SetObjectName( struct ZlangRuntime *rt , struct ZlangObject *obj , char *obj_name )
{
	return _SetObjectName( rt , obj , OFFSETOF(struct ZlangObject,obj_name) , obj_name );
}

int SetObjectEmbellishName( struct ZlangRuntime *rt , struct ZlangObject *obj , char *obj_name )
{
	return _SetObjectName( rt , obj , OFFSETOF(struct ZlangObject,embellish_name) , obj_name );
}

int SetObjectEmbellishName2( struct ZlangRuntime *rt , struct ZlangObject *obj , char *obj_name )
{
	return _SetObjectName( rt , obj , OFFSETOF(struct ZlangObject,embellish2_name) , obj_name );
}

int SetCloneObjectName( struct ZlangRuntime *rt , struct ZlangObject *obj , char *clone_obj_name )
{
	return _SetObjectName( rt , obj , OFFSETOF(struct ZlangObject,clone_obj_name) , clone_obj_name );
}

static char *_GetObjectName( void *obj , size_t offset_of_member )
{
	char		**name = NULL ;
	
	if( obj == NULL )
		return NULL;
	
	name = (char**)( (char*)obj + offset_of_member ) ;
	return (*name);
}

char *GetObjectName( struct ZlangObject *obj )
{
	return _GetObjectName( obj , OFFSETOF(struct ZlangObject,obj_name) );
}

char *GetObjectEmbellishName( struct ZlangObject *obj )
{
	return _GetObjectName( obj , OFFSETOF(struct ZlangObject,embellish_name) );
}

char *GetObjectEmbellishName2( struct ZlangObject *obj )
{
	return _GetObjectName( obj , OFFSETOF(struct ZlangObject,embellish2_name) );
}

char *GetCloneObjectName( struct ZlangObject *obj )
{
	if( obj == NULL )
		return NULL;
	
	return obj->clone_obj_name;
}

struct ZlangFunction *GetFunctionsEntityConstractorFunction( struct ZlangFunctionsEntity *funcs_enti )
{
	if( funcs_enti == NULL )
		return NULL;
	
	return funcs_enti->constractor_cache;
}

struct ZlangFunction *GetFunctionsEntityDestractorFunction( struct ZlangFunctionsEntity *funcs_enti )
{
	if( funcs_enti == NULL )
		return NULL;
	
	return funcs_enti->destractor_cache;
}

int GetFunctionsEntityReferCount( struct ZlangFunctionsEntity *funcs_enti )
{
	if( funcs_enti == NULL )
		return -1;
	
	return funcs_enti->refer_count;
}

unsigned char IsObjectPropertiesEntityNull( struct ZlangObject *obj )
{
	if( obj->funcs_enti == NULL )
		return 1;
	
	if( obj->props_enti == NULL )
		return 1;
	
	return 0;
}

unsigned char IsObjectPropertiesEntityNotNull( struct ZlangObject *obj )
{
	return ! IsObjectPropertiesEntityNull( obj );
}

#if 0
unsigned char IsObjectNull( struct ZlangObject *obj )
{
	if( obj->funcs_enti == NULL )
		return 1;
	else
		return 0;
}
#endif

int IsObjectTrueValue( struct ZlangRuntime *rt , struct ZlangObject *logic_obj , unsigned char *logic_result )
{
	int		nret = 0 ;
	
	if( GetObjectDirectFunctions( logic_obj ) == NULL || IsObjectPropertiesEntityNull( logic_obj ) )
	{
		(*logic_result) = 0 ;
	}
	else if( IsTypeOf( rt , logic_obj , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
	{
		nret = CallRuntimeFunction_bool_GetBoolValue( rt , logic_obj , logic_result );
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_bool_GetBoolValue return[%d]" , nret )
			return nret;
		}
	}
	else if( IsTypeOf( rt , logic_obj , GetShortObjectInRuntimeObjectsHeap(rt) ) )
	{
		int16_t		s ;
		
		nret = CallRuntimeFunction_short_GetShortValue( rt , logic_obj , & s );
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_short_GetShortValu return[%d]" , nret )
			return nret;
		}
		if( s )
			(*logic_result) = 1 ;
		else
			(*logic_result) = 0 ;
	}
	else if( IsTypeOf( rt , logic_obj , GetIntObjectInRuntimeObjectsHeap(rt) ) )
	{
		int32_t		i ;
		
		nret = CallRuntimeFunction_int_GetIntValue( rt , logic_obj , & i );
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_int_GetIntValue return[%d]" , nret )
			return nret;
		}
		if( i )
			(*logic_result) = 1 ;
		else
			(*logic_result) = 0 ;
	}
	else if( IsTypeOf( rt , logic_obj , GetLongObjectInRuntimeObjectsHeap(rt) ) )
	{
		int64_t		l ;
		
		nret = CallRuntimeFunction_long_GetLongValue( rt , logic_obj , & l );
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_long_GetLongValue return[%d]" , nret )
			return nret;
		}
		if( l )
			(*logic_result) = 1 ;
		else
			(*logic_result) = 0 ;
	}
	else if( IsTypeOf( rt , logic_obj , GetFloatObjectInRuntimeObjectsHeap(rt) ) )
	{
		float		f ;
		
		nret = CallRuntimeFunction_float_GetFloatValue( rt , logic_obj , & f );
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_float_GetFloatValue return[%d]" , nret )
			return nret;
		}
		if( f )
			(*logic_result) = 1 ;
		else
			(*logic_result) = 0 ;
	}
	else if( IsTypeOf( rt , logic_obj , GetDoubleObjectInRuntimeObjectsHeap(rt) ) )
	{
		double		d ;
		
		nret = CallRuntimeFunction_double_GetDoubleValue( rt , logic_obj , & d );
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_double_GetDoubleValue return[%d]" , nret )
			return nret;
		}
		if( d )
			(*logic_result) = 1 ;
		else
			(*logic_result) = 0 ;
	}
	else if( IsTypeOf( rt , logic_obj , GetStringObjectInRuntimeObjectsHeap(rt) ) )
	{
		int32_t		str_len ;
		
		nret = CallRuntimeFunction_string_GetStringValue( rt , logic_obj , NULL , & str_len );
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_string_GetStringValue return[%d]" , nret )
			return nret;
		}
		if( str_len > 0 )
			(*logic_result) = 1 ;
		else
			(*logic_result) = 0 ;
	}
	else if( IsTypeOf( rt , logic_obj , GetFunctionPtrObjectInRuntimeObjectsHeap(rt) ) )
	{
		struct ZlangFunction	*func = NULL ;
		
		nret = CallRuntimeFunction_functionptr_GetFunctionPtr( rt , logic_obj , & func );
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_functionptr_GetFunctionPtr return[%d]" , nret )
			return nret;
		}
		if( func )
			(*logic_result) = 1 ;
		else
			(*logic_result) = 0 ;
	}
	else
	{
		return ZLANG_ERROR_UNEXPECT_LOGIC_OBJECT_TYPE;
	}
	
	return 0;
}

struct ZlangObject *AddPropertyInObject( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *parent_obj , char *prop_name )
{
	struct ZlangObject		*prop_obj = NULL ;
	struct ZlangPropertiesEntity	*props_enti = NULL ;
	int				nret = 0 ;
	
	if( parent_obj )
	{
		nret = CloneObject( rt , & prop_obj , prop_name , parent_obj ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneObject[%s] failed[%d]" , GetObjectName(parent_obj) , nret )
			return NULL;
		}
	}
	else
	{
		prop_obj = CloneNullObject( rt , prop_name ) ;
		if( prop_obj == NULL )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CloneNullObject failed[%d]" , nret )
			return NULL;
		}
	}
	
	props_enti = GetObjectPropertiesEntity( obj ) ;
	if( props_enti == NULL )
	{
		nret = InitObject( rt , obj , GetObjectName(obj) , GetObjectDirectFunctions(obj) , 0 ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InitObject failed[%d]" , nret )
			return NULL;
		}
		
		props_enti = GetObjectPropertiesEntity( obj ) ;
	}
	
	nret = LinkPropertyToEntityPropertiesTreeByPropertyName( props_enti , prop_obj ) ;
	if( nret )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_LINK_PROP_TO_ENTITY , "property[%p][%s] add to object[%p][%s] failed[%d]" , prop_obj , GetObjectName(prop_obj) , obj , GetObjectName(obj) , nret )
		return NULL;
	}
	else
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "property[%p][%s] add to object[%p][%s] ok" , prop_obj , GetObjectName(prop_obj) , obj , GetObjectName(obj) )
	}
	
	list_add_tail( & (prop_obj->obj_list_node) , & (props_enti->props_list) );
	
	return prop_obj;
}

int RemovePropertyInObject( struct ZlangRuntime *rt , struct ZlangObject *obj , char *prop_name )
{
	struct ZlangPropertiesEntity		*props_enti = NULL ;
	struct ZlangObject		o ;
	struct ZlangObject		*prop_obj = NULL ;
	
	props_enti = GetObjectPropertiesEntity( obj ) ;
	
	memset( & o , 0x00 , sizeof(struct ZlangObject) );
	o.obj_name = prop_name ;
	prop_obj = QueryPropertyInEntityPropertiesTreeByPropertyName( props_enti , & o ) ;
	TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS_AND_FORMAT( rt , "QueryPropertyInEntityPropertiesTreeByPropertyName prop_name[%s] return prop[%p]" , prop_name , prop_obj ); }
	if( prop_obj == NULL )
	{
		return ZLANG_ERROR_PROP_NOT_FOUND_IN_OBJECT;
	}
	
	UnlinkPropertyFromEntityPropertiesTree( props_enti , prop_obj );
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "property[%s] unlink from object[%s] ok" , prop_name , GetObjectName(obj) )
	
	list_del( & (prop_obj->obj_list_node) );
	
	DestroyObject( rt , prop_obj );
	
	return 0;
}

struct ZlangObject *AddNullPropertyInObject( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *parent_obj , char *prop_name )
{
	struct ZlangObject		*prop_obj = NULL ;
	
	prop_obj = AddPropertyInObject( rt , obj , parent_obj , prop_name ) ;
	if( prop_obj == NULL )
		return NULL;
	
	UnreferObjectPropertiesEntity( rt , prop_obj );
	
	return prop_obj;
}

struct ZlangObject *QueryPropertyInObjectByPropertyName( struct ZlangRuntime *rt , struct ZlangObject *obj , char *prop_name )
{
	struct ZlangPropertiesEntity	*props_enti = NULL ;
	struct ZlangObject		o ;
	struct ZlangObject		*prop = NULL ;
	
	if( obj == NULL )
		return NULL;
	
	props_enti = GetObjectPropertiesEntity(obj) ;
	if( props_enti == NULL )
		return NULL;
	
	memset( & o , 0x00 , sizeof(struct ZlangObject) );
	o.obj_name = prop_name ;
	prop = QueryPropertyInEntityPropertiesTreeByPropertyName( props_enti , & o ) ;
	if( prop == NULL )
	{
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "QueryPropertyInEntityPropertiesTreeByPropertyName " ); DebugPrintObject( rt , obj ); printf( " prop_name[%s] return prop[%p]" , prop_name , prop ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
		return NULL;
	}
	else
	{
		TEST_RUNTIME_DEBUG( rt ) { PRINT_TABS(rt) printf( "QueryPropertyInEntityPropertiesTreeByPropertyName " ); DebugPrintObject( rt , obj ); printf( " prop_name[%s] return " , prop_name ); DebugPrintObject( rt , prop ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "obj[%p] rt->in_obj[%p] prop->access_qualifier[%d]" , obj , rt->in_obj , prop->access_qualifier )
	if( obj == rt->in_obj || prop->access_qualifier == OBJECTACCESSQUALIFIER_PUBLIC )
	{
		;
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_PROPERTY_IS_NOT_PUBLIC , "property '%s' is not public in object '%s'" , prop_name , GetObjectName(obj) )
		return NULL;
	}
	
	return prop;
}

struct ZlangObject *TravelPropertyInObject( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *prop )
{
	struct ZlangPropertiesEntity	*props_enti = NULL ;
	struct ZlangObject		*next_prop = NULL ;
	
	props_enti = GetObjectPropertiesEntity( obj ) ;
	if( props_enti == NULL )
		return NULL;
	
	if( list_empty( & (props_enti->props_list) ) )
		return NULL;
	
	if( prop == NULL )
	{
		next_prop = list_first_entry_or_null( & (props_enti->props_list) , struct ZlangObject , obj_list_node ) ;
	}
	else
	{
		next_prop = list_next_entry_or_null( prop , & (props_enti->props_list) , struct ZlangObject , obj_list_node ) ;
	}
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "prop[%s]'s next prop is[%s]" , GetObjectName(prop) , GetObjectName(next_prop) )
	
	return next_prop;
}

struct ZlangObject *QueryObjectByObjectName( struct ZlangRuntime *rt , char *obj_name , struct ZlangTokenDataUnitHeader *cache_in_token_info )
{
	struct ZlangObject	*obj = NULL ;
	struct ZlangFunction	*func = NULL ;
	int			nret = 0 ;
	
	obj = QueryObjectInLocalObjectsStack( rt , obj_name , cache_in_token_info ) ;
	if( obj )
		return obj;
	
	obj = QueryPropertyInObjectByPropertyName( rt , rt->in_obj , obj_name ) ;
	if( obj )
		return obj;
	
	func = QueryFunctionInObjectByFunctionName( rt , rt->in_obj , obj_name ) ;
	if( func )
	{
		obj = CloneFunctionPtrObjectInTmpStack( rt , NULL ) ;
		if( obj == NULL )
			return NULL;
		
		CallRuntimeFunction_functionptr_SetObjectPtr( rt , obj , rt->in_obj );
		CallRuntimeFunction_functionptr_SetFunctionPtr( rt , obj , func );

		return obj;
	}

	obj = QueryGlobalObjectByObjectName( rt , obj_name ) ;
	if( obj )
		return obj;
	
	func = QueryGlobalFunctionByFunctionName( rt , obj_name ) ;
	if( func )
	{
		obj = CloneFunctionPtrObjectInTmpStack( rt , NULL ) ;
		if( obj == NULL )
			return NULL;
		
		nret = CallRuntimeFunction_functionptr_SetFunctionPtr( rt , obj , func ) ;
		if( nret )
			return NULL;

		return obj;
	}

	return NULL;
}

struct ZlangObject *QueryObjectByObjectNameIncludeLowerLocalObjectsStack( struct ZlangRuntime *rt , char *obj_name , struct ZlangTokenDataUnitHeader *cache_in_token_info )
{
	struct ZlangObject	*obj = NULL ;
	
	obj = QueryObjectInLowerLocalObjectsStack( rt , obj_name , cache_in_token_info ) ;
	if( obj == NULL )
	{
		obj = QueryPropertyInObjectByPropertyName( rt , rt->in_obj , obj_name ) ;
		if( obj == NULL )
		{
			obj = QueryGlobalObjectByObjectName( rt , obj_name ) ;
			if( obj == NULL )
			{
				return NULL;
			}
		}
	}
	
	return obj;
}

struct ZlangObject *QueryGlobalObjectByObjectName( struct ZlangRuntime *rt , char *obj_name )
{
	struct ZlangObject	o ;
	struct ZlangObject	*obj = NULL ;
	
	memset( & o , 0x00 , sizeof(struct ZlangObject) );
	o.obj_name = obj_name ;
	obj = QueryObjectInRuntimeObjectsHeapByObjectName( rt , & o ) ;
	if( obj == NULL )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "QueryObjectInRuntimeObjectsHeapByObjectName[%s] return obj[%p]" , obj_name , obj )
		return NULL;
	}
	else
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "QueryObjectInRuntimeObjectsHeapByObjectName[%s] return obj[%p]" , obj_name , obj )
	}
	
	return obj;
}

void SummarizeObjectDirectPropertySize( struct ZlangRuntime *rt , struct ZlangObject *obj , size_t *summarized_obj_size , size_t *summarized_direct_prop_size )
{
	struct ZlangDirectFunctions	*direct_funcs = NULL ;
	
	direct_funcs = GetObjectDirectFunctions( obj ) ;
	if( direct_funcs == NULL || direct_funcs->summarize_direct_prop_size_func == NULL )
		return;
	
	direct_funcs->summarize_direct_prop_size_func( rt , obj , summarized_obj_size , summarized_direct_prop_size ) ;
	
	return;
}

void SummarizeFunctionSize( struct ZlangRuntime *rt , struct ZlangFunction *func , size_t *summarized_obj_size )
{
	struct ZlangFunctionParameter	*func_param = NULL ;
	
	if( func == NULL )
		return;
	
	if( GetFunctionName(func) )
		SUMMARIZE_SIZE( summarized_obj_size , strlen(GetFunctionName(func))+1 )
	if( GetFullFunctionName(func) )
		SUMMARIZE_SIZE( summarized_obj_size , strlen(GetFullFunctionName(func))+1 )
	
	func_param = NULL ;
	while( ( func_param = TravelFunctionInputParameter(rt,func,func_param) ) )
	{
		if( GetFunctionParameterParentObjectName(func_param) )
			SUMMARIZE_SIZE( summarized_obj_size , strlen(GetFunctionParameterParentObjectName(func_param))+1 )
		if( GetFunctionParameterObjectName(func_param) )
			SUMMARIZE_SIZE( summarized_obj_size , strlen(GetFunctionParameterObjectName(func_param))+1 )
		SUMMARIZE_SIZE( summarized_obj_size , sizeof(struct ZlangFunctionParameter) )
	}
	
	SUMMARIZE_SIZE( summarized_obj_size , sizeof(struct ZlangFunction) )
	
	return;
}

void SummarizeObjectFunctionsEntitySize( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangFunctionsEntity *funcs_enti , size_t *summarized_obj_size )
{
	struct ZlangFunction		*func = NULL ;
	
	if( funcs_enti == NULL )
		return;
	
	func = NULL ;
	while( ( func = TravelFunctionFromFunctionsEntityFunctionsTreeByFullFunctionName(funcs_enti,func) ) )
	{
		SummarizeFunctionSize( rt , func , summarized_obj_size );
	}
	
	return;
}

void SummarizeObjectPropertiesEntitySize( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangPropertiesEntity *props_enti , size_t *summarized_obj_size , size_t *summarized_direct_prop_size )
{
	struct ZlangObject	*prop = NULL ;
	
	if( props_enti == NULL )
		return;
	
	SummarizeObjectDirectPropertySize( rt , obj , summarized_obj_size , summarized_direct_prop_size );
	
	prop = NULL ;
	while( ( prop = TravelPropertyFromEntityPropertiesTreeByPropertyName(props_enti,prop) ) )
	{
		SummarizeObjectSize( rt , prop , summarized_obj_size , summarized_direct_prop_size );
	}
	
	SUMMARIZE_SIZE( summarized_obj_size , sizeof(struct ZlangPropertiesEntity) )
	
	return;
}

void SummarizeObjectSize( struct ZlangRuntime *rt , struct ZlangObject *obj , size_t *summarized_obj_size , size_t *summarized_direct_prop_size )
{
	if( obj->clone_obj_name )
		SUMMARIZE_SIZE( summarized_obj_size , strlen(obj->clone_obj_name)+1 )
	if( obj->obj_name )
		SUMMARIZE_SIZE( summarized_obj_size , strlen(obj->obj_name)+1 )
	if( obj->embellish_name )
		SUMMARIZE_SIZE( summarized_obj_size , strlen(obj->embellish_name)+1 )
	if( obj->embellish2_name )
		SUMMARIZE_SIZE( summarized_obj_size , strlen(obj->embellish2_name)+1 )
	if( obj->funcs_enti )
	{
		SummarizeObjectFunctionsEntitySize( rt , obj , obj->funcs_enti , summarized_obj_size ) ;
	}
	if( obj->props_enti )
	{
		SummarizeObjectPropertiesEntitySize( rt , obj , obj->props_enti , summarized_obj_size , summarized_direct_prop_size );
	}
	SUMMARIZE_SIZE( summarized_obj_size , sizeof(struct ZlangObject) )
	
	return;
}

int CheckUnimplementFunctionInObject( struct ZlangRuntime *rt , struct ZlangObject *top_child_obj , struct ZlangFunctionsEntity *funcs_enti )
{
	struct ZlangFunction	*func = NULL ;
	struct ZlangFunction	*query_func = NULL ;
	int			nret = 0 ;
	
	if( funcs_enti == NULL )
		return 0;
	
	
	if( funcs_enti->ancestor_funcs_enti )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CheckUnimplementFunctionInObject funcs_enti[%p][%d] ..." , funcs_enti,GetFunctionsEntityReferCount(funcs_enti) )
		nret = CheckUnimplementFunctionInObject( rt , top_child_obj , funcs_enti->ancestor_funcs_enti ) ;
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CheckUnimplementFunctionInObject funcs_enti[%p][%d] return[%d]" , funcs_enti,GetFunctionsEntityReferCount(funcs_enti) , nret )
		if( nret )
			return nret;
	}
	
	func = NULL ;
	for( ; ; )
	{
		func = TravelFunctionFromFunctionsEntityFunctionsTreeByFullFunctionName( funcs_enti , func ) ;
		if( func == NULL )
			break;
		
		if( func->func_begin_token_datapage_header == NULL && func->invoke_func == NULL )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "interface func[%s][%s]" , func->func_name , func->full_func_name )
			
			query_func = QueryFunctionInObjectByFullFunctionName( rt , top_child_obj , func->full_func_name ) ;
			if( query_func == NULL || query_func->func_begin_token_datapage_header == NULL )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_UNIMPLEMET_INTERFACE_FUNCTION , "unimplement interface function[%s][%s] in object[%s] defination" , func->func_name , func->full_func_name , GetObjectName(top_child_obj) )
				return 1;
			}
		}
	}
	
	return 0;
}

void DebugPrintObject( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangFunctionsEntity	*ancestor_funcs_enti = NULL ;
	struct ZlangDirectFunctions	*ancestor_direct_funcs = NULL ;
	int				nret = 0 ;
	
	printf( "obj[%p]" , obj );
	
	if( obj == NULL )
		return;
	
	printf( "name[%s][%s][%s][%s]" , obj->clone_obj_name , obj->obj_name , obj->embellish_name , obj->embellish2_name );
	
	if( obj->funcs_enti )
	{
		printf( "access_qualifier[%d]const[%d]atomic[%p]intercept[%p][%p]" , obj->access_qualifier , obj->is_constant , obj->atomic_lock , obj->intercept_set , obj->intercept_get );
		ancestor_funcs_enti = obj->funcs_enti->ancestor_funcs_enti ;
		if( ancestor_funcs_enti )
			ancestor_direct_funcs = ancestor_funcs_enti->direct_funcs ;
		printf( "->funcs_enti[%p][%ld]direct_funcs[%p][%s]ancestor_funcs_enti[%p][%ld]direct_funcs[%p][%s]"
			, obj->funcs_enti,(obj->funcs_enti)?(obj->funcs_enti->refer_count):-1
			, obj->funcs_enti->direct_funcs,(obj->funcs_enti->direct_funcs)?(obj->funcs_enti->direct_funcs->type_name):NULL
			, ancestor_funcs_enti,ancestor_funcs_enti?(ancestor_funcs_enti->refer_count):-1
			, ancestor_direct_funcs,ancestor_direct_funcs?(ancestor_direct_funcs->type_name):NULL );
		printf( "->props_enti[%p][%ld]direct_prop[%p]con/destract[%d][%d]"
			, obj->props_enti,(obj->props_enti)?(obj->props_enti->refer_count):-1
			, (obj->props_enti)?(obj->props_enti->direct_prop):NULL
			, (obj->props_enti)?(obj->props_enti->had_constracted):-1
			, (obj->props_enti)?(obj->props_enti->had_destracted):-1 );
		
		if( rt->frequent_objs.array_obj && obj->funcs_enti->direct_funcs == rt->frequent_objs.array_obj->funcs_enti->direct_funcs )
		{
			if( obj->props_enti && obj->props_enti->direct_prop )
			{
				int32_t			element_no , element_count ;
				struct ZlangObject	*collection_unit_obj = NULL ;
				
				nret = CallRuntimeFunction_array_Length( rt , obj , & element_count ) ;
				if( nret )
					return;
				printf( " array_count[%"PRIi32"]" , element_count );
				
				for( element_no = 1 ; element_no <= element_count ; element_no++ )
				{
					nret = CallRuntimeFunction_array_Get( rt , obj , element_no , & collection_unit_obj ) ;
					if( nret )
						return;
					
					printf( " ->element_no[%"PRIi32"]:" , element_no ); DebugPrintObject( rt , collection_unit_obj );
				}
			}
		}
		else
		{
			if( obj->props_enti == NULL )
			{
				printf( "->data[][%s]" , ZLANG_null_STRING );
			}
			else if( obj->funcs_enti->direct_funcs == NULL || obj->funcs_enti->direct_funcs->to_string_func == NULL )
			{
				printf( "->data[][(no_tostr_func)]" );
			}
			else if( rt->frequent_objs.string_obj && obj->funcs_enti->direct_funcs->to_string_func )
			{
				struct ZlangObject	*tostr_obj = NULL ;
				char			*str = NULL ;
				int32_t			str_len ;
				
				tostr_obj = CloneStringObject( rt , NULL ) ;
				if( tostr_obj == NULL )
					return;
				
				nret = obj->funcs_enti->direct_funcs->to_string_func( rt , obj , & tostr_obj ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "->to_string_func failed[%d]" , nret )
					DestroyObject( rt , tostr_obj );
					return;
				}
				
				nret = GetDataPtr( rt , tostr_obj , (void**) & str , & str_len ) ;
				if( nret )
				{
					DestroyObject( rt , tostr_obj );
					return;
				}
				
				printf( "->data[%d][%.*s%s]" , str_len , (str_len>DEBUG_PRINT_STRING_LEN_MAX?DEBUG_PRINT_STRING_LEN_MAX:str_len),str , (str_len>DEBUG_PRINT_STRING_LEN_MAX?"...":"") );
				
				DestroyObject( rt , tostr_obj );
			}
		}
	}
	else if( obj->props_enti )
	{
		printf( "->props_enti[%p]direct_prop[%p]refer_count[%ld]" , obj->props_enti , (obj->props_enti)?(obj->props_enti->direct_prop):NULL , (obj->props_enti)?(obj->props_enti->refer_count):0 );
	}
	
	return;
}

void DebugPrintObjectFunctions( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
#if 0
	struct ZlangFunction			*func = NULL ;
	
	func_enti = GetObjectFunctionsEntity(obj) ;
	func = NULL ;
	for( ; func_enti ; )
	{
		func = TravelFunctionFromFunctionsEntityFunctionsTreeByFullFunctionName( func_enti , func ) ;
		if( func == NULL )
			break;
		
		// printf( " func_name[%s][%s]" , GetFunctionName(func) , GetFullFunctionName(func) );
		DebugPrintFunction( rt , func );
	}
	
	return 0;
#endif
	struct ZlangFunctionsEntity	*funcs_enti = NULL ;
	
	funcs_enti = GetObjectFunctionsEntity(obj) ;
	if( funcs_enti == NULL )
		return;
	
	DebugPrintFunctionsEntity( rt , obj , GetObjectFunctionsEntity(obj) );

	return;
}

void DebugPrintObjectProperties( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangPropertiesEntity	*props_enti = NULL ;
	struct ZlangObject		*prop = NULL ;
	
	props_enti = GetObjectPropertiesEntity(obj) ;
	if( props_enti == NULL )
		return;
	
	prop = NULL ;
	for( ; ; )
	{
		prop = TravelPropertyFromEntityPropertiesTreeByPropertyName( props_enti , prop ) ;
		if( prop == NULL )
			break;
		
		TEST_RUNTIME_DEBUG( rt )
		{
			PRINT_TABS(rt) printf( "  prop[%p] " , prop ); DebugPrintObject(rt,prop); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE
		}
	}
	
	return;
}

void DebugPrintFunctionsEntity( struct ZlangRuntime *rt , struct ZlangObject *master_obj , struct ZlangFunctionsEntity *funcs_enti )
{
	struct ZlangFunction	*func = NULL ;
	
	if( funcs_enti == NULL )
		return;
	
	func = NULL ;
	for( ; ; )
	{
		func = TravelFunctionFromFunctionsEntityFunctionsTreeByFullFunctionName( funcs_enti , func ) ;
		if( func == NULL )
			break;
		
		DebugPrintFunction( rt , master_obj , func );
	}
	
	if( funcs_enti->ancestor_funcs_enti )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "  ancestor[%p]" , funcs_enti->ancestor_funcs_enti );
		
		OffsetRuntimeRecursizeDepth( rt , 1 );
		
		DebugPrintFunctionsEntity( rt , master_obj , funcs_enti->ancestor_funcs_enti );
		
		OffsetRuntimeRecursizeDepth( rt , -1 );
	}
	
	return;
}

